package yycore {

  import chisel3._
  import chisel3.util._
  import chisel3.util.experimental.BoringUtils
  import common._

  class GPRReadIO extends Bundle() with MyCoreParameter {
    val rs1_addr = Input(UInt(5.W)) // read address 1
    val rs2_addr = Input(UInt(5.W))
    val rs1_data = Output(UInt(DataBits.W)) // out data
    val rs2_data = Output(UInt(DataBits.W))
  }

  class GPRWriteIO extends Bundle() with MyCoreParameter {
    val w_addr = Input(UInt(5.W))
    val w_data = Input(UInt(DataBits.W))
    val rf_wen = Input(Bool())
  }

  class GPRs extends Module with MyCoreParameter {
    val io = IO(new Bundle() {
      val r = new GPRReadIO()
      val w = new GPRWriteIO()
    })

    // GPR
    val regfile = Mem(32, UInt(DataBits.W))

    // output the data
    io.r.rs1_data := Mux(io.r.rs1_addr =/= 0.U, regfile(io.r.rs1_addr), 0.asUInt(DataBits.W))
    io.r.rs2_data := Mux(io.r.rs2_addr =/= 0.U, regfile(io.r.rs2_addr), 0.asUInt(DataBits.W))

    // when write-back signal is valuing
    when(io.w.rf_wen && (io.w.w_addr =/= 0.U)) {
      regfile(io.w.w_addr) := io.w.w_data
    }

    def read(addr: UInt): UInt = Mux(addr === 0.U, 0.U, regfile(addr))
    if(!FPGA){
      BoringUtils.addSource(VecInit((0 to 31).map(i => regfile.read(i.U))), "difftestRegs")
    }
    when(reset.asBool()) {
      for ( i <- 0 until 32) {
        regfile.write(i.U, 0.U)
      }
    }
    
  }

}